iT邦幫忙

2026 iThome 鐵人賽

DAY 26
1
Software Development

從脆弱腳本到可信任測試平台:自動化測試架構30天系列 第 26

Day 26|如何判斷失敗是產品bug還是測試bug?排查順序與邏輯

  • 分享至 

  • xImage
  •  

「當 CI 上的測試案例跳紅燈時,新手 QA 會第一時間跑去修測試程式碼,中階 QA 會第一時間開 Bug 單給開發;而資深 SDET,會先用一套極度嚴密的診斷邏輯,在 3 分鐘內抓出犯罪現場的真兇。」

大家好,我是 Jane,一個每天在第一線處理跨平台(Web & App)自動化測試、跟 CI/CD Pipeline 與各種神秘失敗案例奮戰的自動化測試工程師(SDET)。

恭喜大家跟著我完成了第五部分關於 CI/CD 管道佈署與失敗報告診斷的討論!

從今天開始,我們邁入了整個系列文章的最終篇章:《第六部分:資深測試工程師真正需要處理的問題》

在實務中,當 CI 跳出紅燈時,開發團隊最常發出的質疑就是:

  • 「Jane,你這個測試又壞了吧?是不是你的 Selector 沒抓好,還是環境又 Timeout 了?」

如果每次 CI 跳紅燈,我們都沒辦法給出確鑿的證據,甚至把「測試程式碼寫爛導致的紅燈」當成 Bug 開給開發,久而久之,開發團隊就會對自動化測試產生嚴重的不信任感

今天這篇文章,我們就來建立一套第一線 SDET 的標準排查邏輯與 7 步驟診斷樹,讓你精準切割責任,拿出讓開發團隊心服口服的排查結果!

一、 第一線 SDET 的 7 步驟決策診斷樹 (Decision Tree)

當你看到 CI 上的 pytest 案例顯示 FAILED 時,請嚴格按照以下 7 個順序 進行邏輯排查:

                    ┌─────────────────────────┐
                    │    7 步驟排查決策樹       │
                    └────────────┬────────────┘
                                 │
     ┌───────────────────────────┼───────────────────────────┐
     ▼                           ▼                           ▼
【第一階段:環境與重現】      【第二階段:日誌與資料】      【第三階段:責任歸屬判定】
1. 是否可人工手動重現?    4. 背景 API/Network 是 500? 6. 產品真實 Bug (Product)
2. 是否特定環境獨有?        5. 斷言值是否符合商業規格?   7. 測試腳本/環境 Bug (Test)
3. 測試資料是否一致/過期?

步驟 1:是否可以在該環境『手動重現』?(Manual Reproducibility)

  • 動作:打開測試報告(Day 25 的神器),拿報告裡的帳號密碼與資料,親自在該環境(Staging/Pre-prod)手動操作一遍。
  • 判斷
    • 如果手動點擊也爆出相同的錯誤或畫面 > 確定是產品 Bug!
    • 如果手動操作完全正常 > 進入步驟 2(可能是時序、動畫或測試腳本問題)。

步驟 2:是否只發生於『特定環境』?(Environment Specific)

  • 動作:檢查是只有 CI Docker 容器爆掉,還是 Staging / Local 環境都會爆。
  • 判斷
    • 如果只有 CI 機器爆掉,檢查 CI 機器是否 CPU 100%、記憶體不足(OOM),或是 DNS 網路瞬斷。這屬於 環境/基建問題(Infra Issue)

步驟 3:輸入的測試資料是否正確與有效?(Test Data Validity)

  • 動作:檢查當下帶入的 Token 是否過期?動態建立的商品 ID 是否存在?帳號權限是否被改動?
  • 判斷
    • 如果是因為前置資料寫死或資料庫未重置導致失敗 > 測試資料/腳本 Bug!

步驟 4:背景 HTTP/Network 是 4xx/5xx 還是 Timeout?(Network Failure Type)

  • 動作:看測試報告中的 Network Log。
  • 判斷
    • 如果 API 回傳 500 Internal Server Error502 Bad Gateway > 產品後端/伺服器 Bug!(直接將 API Payload 與 Trace ID 附在 Bug 單上)。
    • 如果 API 回傳 401 Unauthorized403 Forbidden > 檢查是否為測試 Token 生成邏輯失效。

步驟 5:是否為『非同步時序與等待』問題?(Timing & Waiting)

  • 動作:檢查 Log 顯示的是 TimeoutError: Element not visible 還是 AssertionError
  • 判斷
    • 如果是 TimeoutError,且畫面截圖顯示載入 Spinner 還在轉 > 檢查是否為 測試腳本缺乏條件式等待(Day 12),或是產品前端效能嚴重下滑。

步驟 6:斷言(Assertion)的預期值是否符合『最新商業規格』?(Spec Drift)

  • 動作:確認 PM 或開發最近是否有修改需求(例如:折扣計算公式從 9 折改成 85 折)。
  • 判斷
    • 如果需求改了但測試案例沒更新 > 測試程式碼技術債(Spec Outdated),需同步更新測試案例。

步驟 7:定位器(Locator)是否因為 DOM 改版而失效?(DOM Breakage)

  • 動作:檢查 Element 是否變更了 data-testid 或 Class。
  • 判斷
    • 如果功能正常但抓不到元素 > 測試腳本定位器維護問題(Day 13)

二、 Python / pytest 實戰:建立自動化診斷分類標籤

我們可以在 conftest.py 中利用 Hook,根據 Exception 類型自動為失敗案例加上初步的分類標籤,節省排查時間:

Python

# tests/conftest.py
import pytest
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """
    pytest 鉤子:自動分析 Exception 類型,印出初步歸因建議
    """
    outcome = yield
    report = outcome.get_result()

    if report.when == "call" and report.failed:
        exc_info = call.excinfo

        print(f"\n" + "="*50)
        print(f"[SDET 診斷助手] 案例 {item.name} 執行失敗!")

        # 判斷 1: 是否為 Playwright Timeout (通常為 DOM 變更或時序等待問題)
        if exc_info.errisinstance(PlaywrightTimeoutError):
            print("[初步歸因]: ⚠️ 疑似【測試腳本等待問題】或【DOM 定位器失效】")
            print("[建議排查]: 請檢查畫面截圖,確認是否為動畫未完或 data-testid 變更。")

        # 判斷 2: 是否為 pytest AssertionError (商業邏輯斷言失敗)
        elif exc_info.errisinstance(AssertionError):
            print("[初步歸因]: 🔥 疑似【產品真實 Bug】或【需求規格變更 (Spec Drift)】")
            print("[建議排查]: 請對照預期值 (Expected) 與實際值 (Actual),確認商業邏輯。")

        # 判斷 3: 其他 Exception (如 requests.exceptions.HTTPError)
        else:
            print(f"[初步歸因]: ⚡ 疑似【後端 API 異常】或【環境問題】: {exc_info.type.__name__}")

        print("="*50)

三、 第一線 SDET 的報告話術:如何跟開發團隊溝通?

當你排查完畢,確認是產品真實 Bug 時,開 Bug 單的品質決定了開發團隊對你的尊重程度。

❌ 糟糕的溝通方式(引發衝突):

「Jane: 結帳自動化測試爆掉了,CI 亮紅燈,你們 Dev 昨天的 Code 有 Bug,快去看一下!」

(Dev 打開一看,發現連哪裡壞了都沒寫,氣得說:這是你測試寫壞了吧!)

⭕ 高質量的溝通方式(專業且具備證據鏈):

標題: [Bug][Staging][Checkout API] 購買數量為負數時 API 未正確攔截,回傳 500 錯誤

環境: Staging Pipeline Build #1082

排查過程:

  1. 手動於 Staging 環境重現,直接發送 POST /api/v1/checkout 帶入 quantity: -1
  2. 預期結果: API 應回傳 400 Bad Request 與錯誤 JSON。
  3. 實際結果: API 回傳 500 Internal Server Error,後端 Trace ID: tx_998123
  4. 附帶資源: 已附上 Playwright Trace 檔案與 API Request/Response Log。

明日預告

建立了嚴密的失敗排查機制後,下一個資深 SDET 必須面對的長期戰役就是:「自動化測試技術債(Technical Debt)」

為趕時程複製貼上的腳本、從不刪除的廢棄案例、只有原作者看得懂的黑盒子框架……這些技術債是怎麼形成的?

明天 Day 27,我們將深入探討:《 Day 27|自動化測試技術債如何形成?7 大常見的防禦性坑洞與解法 》


上一篇
Day 25|測試失敗後,報告要提供什麼資訊?打造高品質的排查報告
下一篇
Day 27|自動化測試技術債如何形成?7 大常見的防禦性坑洞與解法
系列文
從脆弱腳本到可信任測試平台:自動化測試架構30天30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言